/*
 * Copyright (c) 2010-2020 IISI.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of IISI.
 */
package com.iisigroup.log.analysis.rdbms;

import bo.ReasonEstimateBo;

import com.iisigroup.log.analysis.rdbms.dao.CauseDao;
import com.iisigroup.log.analysis.rdbms.dao.StackTraceDao;
import com.iisigroup.log.analysis.rdbms.dao.StuckDao;
import com.iisigroup.log.analysis.rdbms.dao.TableJDBCDao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * The Class StackTraceBusiness.
 */
public class StackTraceBusiness {    
    //================================================
    //== [Enumeration types] Block Start
    //== [Enumeration types] Block End 
    //================================================
    //== [static variables] Block Start
    private final static Logger LOGGER = LoggerFactory.getLogger(StackTraceBusiness.class);
    
    /***
     * 資料庫表格cause的中文資訊與uid的map
     * ******/
    private final Map<String,Integer> keyCauseMap  =  new HashMap<String,Integer>();
    //== [static variables] Block Stop 
    //================================================
    //== [instance variables] Block Start
    //== [instance variables] Block Stop 
    //================================================
    //== [static Constructor] Block Start
    //== [static Constructor] Block Stop 
    //================================================
    //== [Constructors] Block Start (含init method)
    //== [Constructors] Block Stop 
    //================================================
    //== [Static Method] Block Start
    //== [Static Method] Block Stop 
    //================================================
    //== [Accessor] Block Start
    //== [Accessor] Block Stop 
    //================================================
    //== [Overrided Method] Block Start (Ex. toString/equals+hashCode)
    /**
     * Stack trace migration.
     * 初始資料正規劃程序
     */
    public synchronized void stackTraceMigration(){
        final TableJDBCDao dao = new TableJDBCDao();
        final StackTraceDao stackTraceDao = new StackTraceDao();
        
        int maxUid = dao.countTableSize("STACKTRACE");
        final  List<String> onlineStuckTrace = stackTraceDao.getDistinctStucktraceList(true); 
        this.processInsertData(onlineStuckTrace, true, maxUid+1);
        onlineStuckTrace.clear();
        
        //線上作業stuck trace pattern 存檔完畢
        
        
        int maxUid2 = dao.countTableSize("STACKTRACE");
        final  List<String> offlineStuckTrace = stackTraceDao.getDistinctStucktraceList(false); 
        this.processInsertData(offlineStuckTrace, false, maxUid2+1);
        offlineStuckTrace.clear();
        
        //非線上作業stuck trace pattern 存檔完畢
        
        final Map<String, Integer> map = stackTraceDao.getTackTraceUidMap();
        //得到關聯uid...準備下一步的正規化（將stuck 原始資料拆解成STUCKEVENT,STACKTRACE）
        
        
        int maxUid3 = dao.countTableSize("STUCKEVENT");
        new StuckDao().insertStuckEventData(maxUid3+1, map);
        
    }
    public void processInsertData(final List<String> straceData ,boolean online,int iniUid){
        final CauseDao causeDao  =     new CauseDao() ;
        final StackTraceDao stackTraceDao =new StackTraceDao();
       
        final  String sqlTemplateFalse = "INSERT INTO STACKTRACE (UID, KEY_CAUSE , ONLINE , STACKTRACE ) VALUES (%s ,'%s' ,false,'%s'   ) ;";
        final  String sqlTemplateTrue = "INSERT INTO STACKTRACE (UID, KEY_CAUSE , ONLINE , STACKTRACE ) VALUES (%s ,'%s' ,true,'%s'   ) ;";
        int count =iniUid;
       
        final List<String> sqls  = new ArrayList<String>();
        final Iterator<String> iterator = straceData.iterator();
        while(iterator.hasNext()){
           final  String str = iterator.next();

           count++;
           
           String cause = ReasonEstimateBo.estimateV01(str);
           if(StringUtils.isBlank(cause)){
               cause = "無法判斷者";
           }
           Integer causeUid =  keyCauseMap.get(cause);
           if(causeUid ==null && cause!=null){
               //在map當中找不到時..去DB資料去找尋..
               causeUid = causeDao.getUid(cause.intern());
               
               if(causeUid ==null  ){
                   int causeCount =causeDao. countTableSize("CAUSE");
                   if(causeCount == 16 ||causeCount == 18 ){
                       LOGGER.info("causeCount: {}  " ,causeCount) ;
                       final  Set<Entry<String, Integer>> entrySet = keyCauseMap.entrySet();
                       for(Entry<String, Integer> unit : entrySet){
                           LOGGER.info("key: {};value: {}  " ,unit.getKey(),unit.getValue()) ;
                       }
                       LOGGER.info("causeCount: {}  " ,causeCount) ;
                   }
                   //得到最大筆uid                        
                   int uid =causeCount +1 ;                        
                   causeDao.inserCauseEventData(uid, cause);
                   causeUid = uid;
                   
                   keyCauseMap.put(cause.intern(), causeUid);              
                   
               }else if(causeUid !=null  ){
                   keyCauseMap.put(cause.intern(), causeUid);
               }
           }
           final String sql = String.format(sqlTemplateFalse,count ,causeUid!=null ?causeUid :cause  , str );
           
           final String sql1 = String.format(sqlTemplateTrue,count , causeUid!=null ?causeUid :cause  , str );
           if(causeUid == null){
               LOGGER.info("causeUid: {} ; cause: {} ;sql: {}" , causeUid,cause ,online?sql1:sql) ;
           }
           if(online){
               sqls.add(sql1);
           }else{
               sqls.add(sql);
           }
           iterator.remove();
        }        
        stackTraceDao.insertDataByswlList(sqls);
    }
    //== [Overrided Method] Block Stop 
    //================================================
    //== [Method] Block Start
    //####################################################################
    //## [Method] sub-block : 
    //####################################################################    
    //== [Method] Block Stop 
    //================================================
    //== [Inner Class] Block Start
    //== [Inner Class] Block Stop 
    //================================================
}
